package middleware

import (
	"fmt"
	"time"

	"gitee.com/go-course/go11/devcloud-mini/maudit/apps/log"
	"gitee.com/go-course/go11/devcloud-mini/mcenter/apps/token"
	"github.com/emicklei/go-restful/v3"

	kafka "github.com/segmentio/kafka-go"
)

// 中间件构造函数
func NewAuditSendor(service string) restful.FilterFunction {
	// 直接通过环境变量获取到kafka配置, 从环境变量读取中间件配置
	conf, err := LoadConfigFromEnv()
	if err != nil {
		panic(err)
	}
	return NewOperateAuditClient(service, conf.GetWriter()).Filter
}

func NewOperateAuditClient(service string, kafka *kafka.Writer) *OperateAuditClient {
	return &OperateAuditClient{
		kafka:   kafka,
		service: service,
	}
}

type OperateAuditClient struct {
	// 同步 rpc, 异步 mq
	// c       *rpc.Client
	// kafka producer
	kafka   *kafka.Writer
	service string
}

func (o *OperateAuditClient) Filter(
	req *restful.Request,
	w *restful.Response,
	next *restful.FilterChain) {
	// 1. 获取Operte Log, 和做权限判断逻辑一样
	auditEnabled := false
	route := req.SelectedRoute()
	meta := route.Metadata()
	audit := meta["audit"]
	if audit != nil {
		if v, ok := audit.(bool); ok {
			auditEnabled = v
		}
	}

	if auditEnabled {
		record := &log.OperateLog{
			Time: time.Now().Unix(),
		}

		// 认证通过后需要把认证通过的信息放到上下文中去
		tkAttr := req.Attribute(token.CONTEXT_ATTRIBUTE_KEY)
		if tkAttr != nil {
			tk := tkAttr.(*token.Token)
			record.User = tk.Username

			resource, action := "", ""
			// 根据用户的角色来判断 用户是否可以访问该服务的接口
			resourcev := meta["resource"]
			if resourcev != nil {
				resource = resourcev.(string)
			}

			actionv := meta["action"]
			if actionv != nil {
				action = actionv.(string)
			}
			record.Operation = fmt.Sprintf("%s:%s:%s", o.service, resource, action)

			// 2. 使用kafka的客户端进行发送
			err := o.kafka.WriteMessages(
				req.Request.Context(),
				kafka.Message{
					Value: record.MustToJSON(),
				},
			)
			fmt.Println(err)
		}
	}

	// Gin Next
	next.ProcessFilter(req, w)

}
